package com.codeying.dao;

import com.codeying.utils.JdbcUtils;
import com.codeying.utils.component.JdbcEntity;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *  通用Dao，抽取了一些公共方法
 */
public abstract class AbstractDao<T> {

    protected String clazzName = this.getClass().getName();
    //获取泛型T的class
    protected abstract Class<T> clazz();

    protected abstract String tbName();
    /**
     * 获取where后面的sql语句
     */
    public abstract String toConditionSql(Map<String, String> paramMap);
    /**
     * 根据参数查询数据
     */
    public List<T> list(Map<String, String> paramMap){
        try{
            QueryRunner qr = new QueryRunner();
            //将参数列表转换成查询条件
            String queryCondition = toConditionSql(paramMap);
            //获取分页信息
            Integer pageIndex = 1;
            Integer pageSize = null;
            if(paramMap!=null){
                try {
                    pageIndex = Integer.parseInt( paramMap.get("pageIndex"));
                    pageSize = Integer.parseInt(paramMap.get("pageSize"));
                }catch (Exception e){}
            }
            //接下来拼接查询条件，然后获取分页sql
            String sqlRes = JdbcUtils.getPageSql("SELECT * FROM "+tbName()+" where 1=1 " + queryCondition, pageIndex,pageSize);
            //打印sql语句和参数
            log(sqlRes);
            //执行查询
            List<T> list = qr.query(JdbcUtils.getConnection(), sqlRes, new BeanListHandler<>(clazz()));
            return list;
        }catch (Exception e){
            e.printStackTrace();
            System.out.println(tbName() + "Dao -> list(...)报错了");
        }
        return new ArrayList();
    }
    /**
     * 根据ID获取一个记录
     */
    public T getById(String id){
        return getBy("id",id);
    }
    /**
     * 新增
     */
    public abstract int insert(T t);
    /**
     * 更新
     */
    public abstract int updateById(T t);
    /**
     * 根据..条件获取一条数据
     */
    public T getBy(String paramName, String val) {
        try {
            QueryRunner qr = new QueryRunner();
            String sqlBuilder = "SELECT * FROM " + tbName() + " where " + paramName + " = ?";
            //log
            log(sqlBuilder + " 。 " + val);
            List<T> list = qr.query(JdbcUtils.getConnection(), sqlBuilder, new BeanListHandler<>(clazz()), val);
            if (list.size() > 0) return list.get(0);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(clazzName + " -> getBy" + paramName + ": val:" + val + "报错了");
        }
        return null;
    }
    /**
     * 查询所有
     */
    public List<T> list() {
        return list(null);
    }
    /**
     * 通用方法 ，总记录数
     */
    public Integer count(){
        return count("");
    }
    public Integer count(Map<String,String> paramMap){
        return count("where 1=1 " + toConditionSql(paramMap));
    }
    public Integer count(String lastSql){ //重载，可拼接条件
        try {
            QueryRunner qr = new QueryRunner();
            String sqlBuilder = "select count(1) as intP from " + tbName() + " " + lastSql;
            log(sqlBuilder);
            List<JdbcEntity> list = qr.query(JdbcUtils.getConnection(),sqlBuilder,null, new BeanListHandler<>(JdbcEntity.class));
            if (list.size() > 0) {
                return list.get(0).getIntP();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(clazzName + " -> count()  " + "报错了");
        }
        return null;
    }
    public double avg(Map<String, String> paramMap, String column) {
        String conditionSql = toConditionSql(paramMap);
        try {
            QueryRunner qr = new QueryRunner();
            String sqlBuilder = "select avg("+column+") as doubleP from " + tbName() + " where 1=1 " + conditionSql;
            log(sqlBuilder);
            List<JdbcEntity> list = qr.query(JdbcUtils.getConnection(),sqlBuilder,null, new BeanListHandler<>(JdbcEntity.class));
            if (list.size() > 0 && list.get(0).getDoubleP() !=null ) {
                return list.get(0).getDoubleP();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(clazzName + " -> avg()  " + "报错了");
        }
        return 0;
    }
    public double sum(Map<String, String> paramMap, String column) {
        String conditionSql = toConditionSql(paramMap);
        try {
            QueryRunner qr = new QueryRunner();
            String sqlBuilder = "select sum("+column+") as doubleP from " + tbName() + "  where 1=1 " + conditionSql;
            log(sqlBuilder);
            List<JdbcEntity> list = qr.query(JdbcUtils.getConnection(),sqlBuilder,null, new BeanListHandler<>(JdbcEntity.class));
            if (list.size() > 0  && list.get(0).getDoubleP() !=null ) {
                return list.get(0).getDoubleP();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(clazzName + " -> sum()  " + "报错了");
        }
        return 0;
    }
    /**
     * 根据id删除
     */
    public int deleteById(String id) {
        return delete("where id='"+id+"' ");
    }

    public int delete(Map<String, String> paramMap){
        String conditionSql = toConditionSql(paramMap);
        return delete("where 1=1 " + conditionSql);
    }

    /**
     * 删除
     */
    public int delete(String whereSql) {
        try{
            QueryRunner qr = new QueryRunner();  //创建QueryRunner类对象
            String sqlBuilder = "delete from " + tbName() + " " + whereSql;
            //输出sql语句
            log(sqlBuilder);
            return qr.update(JdbcUtils.getConnection(), sqlBuilder);  // 执行SQL语句
        }catch (Exception e){
            e.printStackTrace();
            System.out.println(clazzName + " -> delete报错了");
        }
        return 0;
    }

    /**
     * 打印执行记录到控制台
     */
    protected void log(String sql){
        log(sql,null);
    }
    protected void log(String sql, List<Object> params){
        System.out.println("-------------------------------");
        System.out.println(">>>执行sql语句：" + sql);
        if(params!=null){
            System.out.print(">>>参数：");
            for(Object o : params){
                System.out.print("["+o+"] ");
            }
        }
        System.out.println("\n-------------------------------");
    }
}
